package com.domain.common.signature;

import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

public class Signature {
	private final static String key = "2F7216D926A9186B148FAE6BECFF7C74";
	private final static String SIGNNAME = "APISIGNNAME";
	private final static String TIMESTAMP = "APIACCESSTIMESTAMP";

	/**
	 * 为请求添加签名
	 * 
	 * @param map
	 * @return
	 */
	public static Map<String, String> signMap(Map<String, String> map) {
		if (null == map) {
			map = new HashMap<>();
		}
		map.put(TIMESTAMP, "ATT" + System.currentTimeMillis());
		String signString = getSignString(map);
		map.put(SIGNNAME, signString);
		return map;
	}

	public static boolean getSignFromResponseString(Map<String, String> map) {
		if (null == map) {
			return false;
		}
		Object sign = map.get(SIGNNAME);
		String string = sign.toString();
		if (null == string || "".equals(string)) {
			return false;
		}
		// map.remove(SIGNNAME);
		// 将API返回的数据根据用签名算法进行计算新的签名，用来跟API返回的签名进行比较
		return string.equals(Signature.getSignString(map));
	}

	public static boolean getSignFromResponse(Map<String, String[]> map) {
		if (null == map) {
			return false;
		}
		String[] sign = map.get(SIGNNAME);
		if (null == sign) {
			return false;
		}
		String string = sign[0];
		if (null == string || "".equals(string)) {
			return false;
		}
		// map.remove(SIGNNAME);
		// map.put(SIGNNAME, null);
		// 将API返回的数据根据用签名算法进行计算新的签名，用来跟API返回的签名进行比较
		return string.equals(Signature.getSign(map));
	}

	/**
	 * 用于处理请求过来的参数
	 * 
	 * @param map
	 * @return
	 */
	private static String getSign(Map<String, String[]> map) {
		ArrayList<String> list = new ArrayList<String>();
		for (Map.Entry<String, String[]> entry : map.entrySet()) {
			if (null == entry.getKey() || SIGNNAME.equals(entry.getKey())) {
				continue;
			}
			if (entry.getValue() != null && entry.getValue()[0] != null && !"".equals(entry.getValue()[0])) {
				list.add(entry.getKey() + "=" + entry.getValue()[0] + "&");
			}
		}
		int size = list.size();
		String[] arrayToSort = list.toArray(new String[size]);
		Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER);
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < size; i++) {
			sb.append(arrayToSort[i]);
		}
		String result = sb.toString();
		result += "key=" + key;
		result = MD5Encode(result).toUpperCase();
		return result;
	}

	private static String getSignString(Map<String, String> map) {
		ArrayList<String> list = new ArrayList<String>();
		for (Map.Entry<String, String> entry : map.entrySet()) {
			if (null == entry.getKey() || SIGNNAME.equals(entry.getKey())) {
				continue;
			}
			if (entry.getValue() != null && entry.getValue() != "") {
				list.add(entry.getKey() + "=" + entry.getValue() + "&");
			}
		}
		int size = list.size();
		String[] arrayToSort = list.toArray(new String[size]);
		Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER);
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < size; i++) {
			sb.append(arrayToSort[i]);
		}
		String result = sb.toString();
		result += "key=" + key;
		result = MD5Encode(result).toUpperCase();
		return result;
	}

	private static String MD5Encode(String origin) {
		String resultString = null;
		try {
			resultString = origin;
			MessageDigest md = MessageDigest.getInstance("MD5");
			resultString = byteArrayToHexString(md.digest(resultString.getBytes("UTF-8")));
		} catch (Exception e) {
			e.printStackTrace();
		}
		return resultString;
	}

	private static String byteArrayToHexString(byte[] b) {
		StringBuilder resultSb = new StringBuilder();
		for (byte aB : b) {
			resultSb.append(byteToHexString(aB));
		}
		return resultSb.toString();
	}

	private final static String[] hexDigits = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d",
			"e", "f" };

	private static String byteToHexString(byte b) {
		int n = b;
		if (n < 0) {
			n = 256 + n;
		}
		int d1 = n / 16;
		int d2 = n % 16;
		return hexDigits[d1] + hexDigits[d2];
	}

}
